#include <stx/imp/cmn.hpp>

inline namespace stx
{
PodBuffer<std::random_device::result_type>
tlsRandSeeds(std::size_t const seed_cnt)
{
    // libstdc++ uses /dev/urandom by default.
    // See:
    //     void random_device::_M_init(const std::string& token);
    //     [libstdc++-v3/src/c++11/random.cc]

    thread_local auto tls_rd = std::random_device();

    auto ret = PodBuffer<std::random_device::result_type>(seed_cnt);
    std::generate_n(ret.begin(), seed_cnt, std::ref(tls_rd));

    return ret;
}

PodBuffer<std::random_device::result_type> tlsRandSeeds()
{
    return tlsRandSeeds(128uz);
}

std::default_random_engine& tlsRandEngine()
{
    thread_local auto const tls_seeds = tlsRandSeeds(128uz);
    thread_local auto       tls_seed_seq =
        std::seed_seq(std::begin(tls_seeds), std::end(tls_seeds));
    thread_local auto tls_rnd_engine = std::default_random_engine(tls_seed_seq);
    return tls_rnd_engine;
}

std::string genUuidString(SbLowercase const sb_lowercase)
{
    auto buf = std::array<char, 16>{};
    randomize(buf);
    return bin2hex(std::data(buf), std::size(buf), sb_lowercase);
}

std::string genUuidString()
{
    return genUuidString(SbLowercase{});
}

TlsUniformIntRandGenerator<std::uint64_t>& tlsRandGenerator()
{
    thread_local auto tls = TlsUniformIntRandGenerator<std::uint64_t>{};
    return tls;
}

Buffer genRandBuffer(std::size_t const min_len, std::size_t const max_len)
{
    ASSERT(EXPR(max_len > 0) && EXPR(min_len <= max_len), min_len, max_len);

    auto ret = Buffer{};
    resizeDefaultInit(ret, rand(min_len, max_len));
    randomize(ret);
    return ret;
}

std::string genRandString(std::size_t const min_len, std::size_t const max_len)
{
    ASSERT(EXPR(max_len > 0) && EXPR(min_len <= max_len), min_len, max_len);

    static constexpr auto ls_chars =
        "abcdefghijklmnopqrstuvwxyz"
        "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
        "0123456789"sv;

    auto ret = std::string{};
    resizeDefaultInit(ret, rand(min_len, max_len));

    for (auto& c : ret)
    {
        c = ls_chars[rand(0uz, 61uz)];
    }

    return ret;
}
} // namespace stx